  /******************************************************************************
  * @file    PT32X005_spi.c
  * @author  应用开发团队
  * @version V1.1.0
  * @date    2020/1/27
  * @brief    This file provides firmware functions to manage the following
  *          functionalities of the Serial peripheral interface (SPI):
  *           + Initialization and Configuration
  *           + Data transfers functions
  *           + Interrupts and flags management
  *
  ******************************************************************************
  * @attention
  *
  *
  *****************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "PT32X005_spi.h"


/** @defgroup SPI
  * @brief SPI driver modules
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define CR1_CLEAR_MASK2      ((u16)0xFFFB)
#define CR2_LDMA_MASK        ((u16)0x9FFF)

#define I2SCFGR_CLEAR_Mask   ((u16)0xF040)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


/**
  * @brief  Initializes the SPIx  peripheral according to
  *            the specified parameters in the SPI_InitTypeDef.
  * @param  SPIx: select the PWM peripheral.
  * @param  SPI_InitStruct: pointer to a SPI_InitTypeDef
  *         structure that contains the configuration information for
  *         the specified SPI peripheral.
  * @retval None
  */
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
{
	u16 tmpreg = 0;
	/* check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(SPIx));
	/* Check the SPI parameters */
	assert_param(IS_SPI_MSM_SEL(SPI_InitStruct->SPI_Mode));
	assert_param(IS_SPI_DFF_SEL(SPI_InitStruct->SPI_DataSize));
	assert_param(IS_SPI_CPOL_SEL(SPI_InitStruct->SPI_CPOL));
	assert_param(IS_SPI_CPHA_SEL(SPI_InitStruct->SPI_CPHA));

	assert_param(IS_SPI_CSS_SEL(SPI_InitStruct->SPI_CSS));
	assert_param(IS_SPI_SWCS_SEL(SPI_InitStruct->SPI_SWCS));

	assert_param(IS_SPI_SCR_VAL(SPI_InitStruct->SPI_SCR));
	assert_param(IS_SPI_BR_VAL(SPI_InitStruct->SPI_BR ));
	/*---------------------------- SPIx CR1 Configuration ------------------------*/
	/* Get the SPIx CR0 value */
	tmpreg = SPIx->CR1;
	/* Clear DSS,CPOL,CPHA and post BaudRatePrescaler bits */
	tmpreg &= 0x0030;
	/* Configure SPIx: direction, NSS management, first transmitted bit, BaudRate prescaler
	master/slave mode, CPOL and CPHA */
	/* Set BIDImode, BIDIOE and RxONLY bits according to SPI_Direction value */
	/* Set SSM, SSI bit according to SPI_CSS values */
	/* Set LSBFirst bit according to SPI_FirstBit value */
	/* Set BR bits according to SPI_SCR value */
	/* Set CPOL bit according to SPI_CPOL value */
	/* Set CPHA bit according to SPI_CPHA value */
	tmpreg |= (u16)((u32)SPI_InitStruct->SPI_DataSize | SPI_InitStruct->SPI_CPOL |
	                     SPI_InitStruct->SPI_CPHA | ((SPI_InitStruct->SPI_SCR) << 8));
	/* Write to SPIx CR1 */
	SPIx->CR1 = tmpreg;
	/*-------------------------SPI Mode Configuration -----------------------*/
	/* Clear MS bits */
	SPIx->CR2 &= (u16)~SPI_CR2_MSM;
	/* Configure SPIx: Mode */
	SPIx->CR2 |= (u16)(SPI_InitStruct->SPI_Mode);
	/*---------------------------- SPIx CPSR Configuration --------------------*/
	/* Write to SPIx Prescaler */
	SPIx->BR = SPI_InitStruct->SPI_BR;

	tmpreg=SPI_InitStruct->SPI_CSS | SPI_InitStruct->SPI_SWCS;
	SPIx->CSS = tmpreg;
}

/**
  * @brief  Fills each SPI_InitStruct member with its default value.
  * @param  SPI_InitStruct: pointer to a SPI_InitTypeDef structure which will be initialized.
  * @retval None
  */
void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct)
{
	/*--------------- Reset SPI init structure parameters values -----------------*/
	/* Initialize the SPI_Mode member */
	SPI_InitStruct->SPI_Mode = SPI_CR2_MSM_Slave;
	/* Initialize the SPI_DataSize member */
	SPI_InitStruct->SPI_DataSize = SPI_CR1_DFF_8b;
	/* Initialize the SPI_CPOL member */
	SPI_InitStruct->SPI_CPOL = SPI_CPOL_Low;
	/* Initialize the SPI_CPHA member */
	SPI_InitStruct->SPI_CPHA = SPI_CPHA_1Edge;
	/* Initialize the SPI_CSS member */
	SPI_InitStruct->SPI_CSS = SPI_CSS_Hard;
	/* Initialize the SPI_SWCS member */
	SPI_InitStruct->SPI_SWCS = SPI_SWCS_High;
	/* Initialize the SPI_SCR member */
	SPI_InitStruct->SPI_SCR = 2;
	/* Initialize the SPI_BaudRatePrescaler member */
	SPI_InitStruct->SPI_BR = 16;
}

/**
  * @brief  Enables or disables the specified SPI peripheral.
  * @param  SPIx: select the PWM peripheral.
  * @param  NewState: new state of the SPIx peripheral.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState)
{
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(SPIx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
		/* Enable the selected SPI peripheral */
		SPIx->CR2 |= SPI_CR2_SPE;
	}
	else
	{
		/* Disable the selected SPI peripheral */
		SPIx->CR2 &= (u16)~((u16)SPI_CR2_SPE);
	}
}


/**
  * @brief  Configures internally by software the CS pin for the selected SPI.
  * @param  SPIx: select the PWM peripheral.
  * @param  SPI_SWCS_SEL: specifies the SPI CS internal state.
  *          This parameter can be one of the following values:
  *            @arg SPI_SWCS_Low: Set CS pin internally
  *            @arg SPI_SWCS_High: Reset CS pin internally
  * @retval None
  */
void SPI_CSInternalSoftwareConfig(SPI_TypeDef* SPIx, u16 SPI_SWCS_SEL)
{
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(SPIx));
	assert_param(IS_SPI_SWCS_SEL(SPI_SWCS_SEL));
	if (SPI_SWCS_SEL != SPI_SWCS_Low)
	{
		/* Set NSS pin internally by software */
		SPIx->CSS |= SPI_SWCS_High;
	}
	else
	{
		/* Reset NSS pin internally by software */
		SPIx->CSS &= (~SPI_SWCS_High);
	}
}


/**
  * @brief  Transmits a Data through the SPIx peripheral.
  * @param  SPIx: select the PWM peripheral.
  * @param  Data: Data to be transmitted.
  * @retval None
  */
void SPI_SendData(SPI_TypeDef* SPIx, u16 Data)
{
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(SPIx));

	/* Write in the DR register the data to be sent */
	SPIx->DR = Data;
}

/**
  * @brief  Returns the most recent received data by the SPIx peripheral.
  * @param  SPIx: select the PWM peripheral.
  * @retval The value of the received data.
  */
u16 SPI_ReceiveData(SPI_TypeDef* SPIx)
{
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(SPIx));

	/* Return the data in the DR register */
	return SPIx->DR;
}


/**
  * @brief  Enables or disables the specified SPI interrupts.
  * @param  SPIx: select the PWM peripheral.
  * @param  SPI_IT: specifies the SPI interrupt source to be enabled or disabled.
  *          This parameter can be one of the following values:
  *            @arg SPI_IE_OVRE
  *            @arg SPI_IE_OTE
  *            @arg SPI_IE_RXHE
  *            @arg SPI_IE_TXHE
  * @param  NewState: new state of the specified SPI interrupt.
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void SPI_ITConfig(SPI_TypeDef* SPIx, u8 SPI_IT, FunctionalState NewState)
{
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(SPIx));
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	assert_param(IS_SPI_IE_SEL(SPI_IT));
	if (NewState != DISABLE)
	{
		/* Enable the selected SPI interrupt */
		SPIx->IE |= SPI_IT;
	}
	else
	{
		/* Disable the selected SPI interrupt */
		SPIx->IE &= (u16)~SPI_IT;
	}
}

/**
  * @brief  Checks whether the specified SPI flag is set or not.
  * @param  SPIx: select the PWM peripheral.
  * @param  SPI_FLAG: specifies the SPI flag to check.
  *          This parameter can be one of the following values:
  *            @arg SPI_FLAG_TXE
  *            @arg SPI_FLAG_TNF
  *            @arg SPI_FLAG_RXNE
  *            @arg SPI_FLAG_RXF
  *            @arg SPI_FLAG_BSY
  *            @arg SPI_FLAG_OVR
  *            @arg SPI_FLAG_OT
  *            @arg SPI_FLAG_RXH
  *            @arg SPI_FLAG_TXH
  * @retval The new state of SPI_FLAG (SET or RESET).
  */
FlagStatus SPI_GetFlagStatus(SPI_TypeDef* SPIx, u16 SPI_FLAG)
{
	FlagStatus bitstatus = RESET;
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(SPIx));
	assert_param(IS_SPI_SR_SEL(SPI_FLAG));
	/* Check the status of the specified SPI flag */
	if(SPI_FLAG<=SPI_FLAG_BSY)
	{
		if ((SPIx->SR1 & (((u16)0x0001)<<SPI_FLAG)) != (u16)RESET)
		{
			/* */
			bitstatus = SET;
		}
		else
		{
			/* */
			bitstatus = RESET;
		}
	}
	else
	{
		if ((SPIx->SR2 & (((u16)0x0001)<<(SPI_FLAG-5))) != (u16)RESET)
		{
			/* */
			bitstatus = SET;
		}
		else
		{
			/* */
			bitstatus = RESET;
		}
	}
	/*  */
	return  bitstatus;
}

/**
  * @brief  Clears the SPIx flag.
  * @param  SPIx: select the PWM peripheral.
  * @param  SPI_FLAG: Specify the flag to be cleared.
  *         This parameter can be one of the following values:
  *         @arg SPI_IFC_OVR
  *         @arg SPI_IFC_OT
  * @retval None
  */
void SPI_ClearFlag(SPI_TypeDef* SPIx, u16 SPI_FLAG)
{
	/* Check the parameters */
	assert_param(IS_SPI_ALL_PERIPH(SPIx));
	assert_param(IS_SPI_IFC_SEL(SPI_FLAG));

	SPIx->IFC |= SPI_FLAG;
}



/**
  * @}
  */

